package org.anddev.andengine.extension.svg;
/**
 * @author Eric Depta
 * @since 01:14:00 - 28.02.2011
 */
import org.anddev.andengine.extension.svg.util.transform.Rotate;
import org.anddev.andengine.extension.svg.util.transform.Scale;
import org.anddev.andengine.extension.svg.util.transform.TransformDoc;
import org.anddev.andengine.extension.svg.util.transform.Translate;
import org.anddev.andengine.util.MathUtils;


/*
 * matrix(<a> <b> <c> <d> <e> <f>)
 * translate(<tx> [<ty>])
 * scale(<sx> [<sy>])
 * rotate(<rotate-angle> [<cx> <cy>])
 * skewX(<skew-angle>) - no support
 * skewY(<skew-angle>) - no support
 */
public class SVGTransform {
	private int q = 0; 
	private String mTransform = "";
	private TransformDoc mDoc;
	
	public SVGTransform(){
		this.mDoc = new TransformDoc();
	}
	
	public SVGTransform(final String pTransform, final TransformDoc pTransformDoc){
		this.mTransform = pTransform;
		this.mDoc = new TransformDoc();
		this.nextOparation();
		pTransformDoc.transformDoc(this.mDoc);
	}
	
	private void nextOparation(){
		char currChar = ' ';
		while(this.q < this.mTransform.length()){
			currChar = this.mTransform.charAt(this.q);
			if(currChar!=' '){
				this.doOperation(currChar);
				break;
			}else{
				this.q ++;
			}
		}
	}
	
	private void doOperation(final char pChar){
		switch(pChar){
			case 'm':
				//matrix
				this.q += 7;
				this.matrix();
				break;
			case 'r':
				//rotate
				this.q += 7;
				this.rotate();
				break;
			case 't':
				//translate
				this.q += 10;
				this.translate();
				break;
			case 's':
				if(this.mTransform.charAt(this.q+4)=='e'){
					//scale
					this.q += 6;
					this.scale();
				}else{
					//- skewX,skewY not supported
					this.skipWrapedValues();
				}
				break;
		}
		this.nextOparation();
	}
	private void translate(){
		final float[] vals = this.getWrapedValues();
		if(vals.length==1){
			Translate.transformDoc(this.mDoc, vals[0], 0);
		}else{
			Translate.transformDoc(this.mDoc, vals[0], vals[1]);
		}
	}
	private void rotate(){
		final float[] vals = this.getWrapedValues();
		if(vals.length==1){
			Rotate.transformDoc(this.mDoc, vals[0], 0, 0);
		}else{
			Rotate.transformDoc(this.mDoc, vals[0], vals[1], vals[2]);
		}
	}
	private void scale(){
		final float[] vals = this.getWrapedValues();
		if(vals.length==1){
			Scale.transformDoc(this.mDoc, vals[0], vals[0]);
		}else{
			Scale.transformDoc(this.mDoc, vals[0],vals[1]);
		}
	}
	private void matrix(){
		final float[] vals = this.getWrapedValues();
		//-- no skew
		//-- translate
		final float tx = vals[4];
		final float ty = vals[5];
		//-- scale
		final int sign = ((vals[0]*vals[3] - vals[2]*vals[1])<0) ? -1 : 1;
		//TODO round scaling
		final float sx = (float) (sign * Math.sqrt(vals[0]*vals[0] + vals[2]*vals[2]));
		final float sy = (float) (sign * Math.sqrt(vals[1]*vals[1] + vals[3]*vals[3]));
		//-- rotate around z
		final float r = (float) - Math.atan2( vals[2] / sx, vals[0] / sx);
		
		Translate.transformDoc(this.mDoc, tx, ty);
		Scale.transformDoc(this.mDoc,sx,sy);
		Rotate.transformDoc(this.mDoc, MathUtils.radToDeg(r), 0, 0);
	}
	
	private void skipWrapedValues(){
		while(this.q<this.mTransform.length()){
			if(this.mTransform.charAt(this.q)==')'){
				this.q++;
				break;
			}
			this.q++;
		}
	}
	
	private float[] getWrapedValues(){
		char currChar = ' ';
		String valStr = "";
		
		while(this.q<this.mTransform.length()){
			currChar = this.mTransform.charAt(this.q);
			if(currChar==')'){
				this.q++;
				break;
			}else{
				valStr += currChar;
			}
			this.q++;
		}
		// better regular expression ?
		String[] strArr = null;
		if(valStr.indexOf(',')!=-1){
			strArr = valStr.split(",");
		}else{
			strArr = valStr.split(" ");
		}
		
		float[] vals = new float[strArr.length];
		
		for(int i=0;i<strArr.length;i++){
			vals[i] = Float.parseFloat(strArr[i]);
		}
		
		return vals;
	}
	public TransformDoc getDoc(){
		return this.mDoc;
	}
}
